package com.wichatbackapi.config;

import com.wichatbackapi.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Collections;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity//开启注解权限配置
public class SecurityConfig {//Security的配置类
    /**
     * 自定义授权拦截器
     */
    @Autowired
    private JwtAuthenticationTokenFilter LoginJwtFilter;
//    @Autowired
//    UserDetailsService userDetailsService;

    /**
     * 强散列哈希加密实现 没有这个会报错 There is no PasswordEncoder mapped for the id “null“
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //暴露出来 解决无法直接注入 AuthenticationManager
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    /**
     * 配置类
     *
     * @param httpSecurity HttpSecurity
     * @throws Exception Exception
     */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 设置访问权限
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/login/**", "/register/**", "/getCheckCode").permitAll()
                        .requestMatchers(HttpMethod.GET, "/", "/*.html", "/*.css", "/*.js",
                                "/*/*.html", "/*/*.css", "/*/*.js", "/*/api-docs/**",
                                "/webjars/**", "/*.ioc").permitAll()
                        .anyRequest().authenticated()
                )
                //  禁用默认登录页
                .formLogin(fl ->
                        fl.disable()
                )
                //  禁用默认登出页
                .logout(lt ->
                        lt.logoutUrl("/security/logout")
                )
                // 跨域处理
                .cors(cors ->cors.configurationSource(configurationSource()))
                // 关闭 CSRF跨站请求伪造
                .csrf(csrf -> csrf.disable())
                //  设置 处理鉴权失败、认证失败
                .exceptionHandling(exceptionHandling ->
                        // 配置自定义的异常处理逻辑
                        exceptionHandling
                                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
                );
        //  添加过滤器
        httpSecurity.addFilterBefore(LoginJwtFilter, UsernamePasswordAuthenticationFilter.class);

        return httpSecurity.build();
    }
    /**
     * 跨域解决方案
     *
     * @return CorsConfigurationSource
     */
    CorsConfigurationSource configurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
        corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
        corsConfiguration.setAllowedOrigins(Collections.singletonList("*"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return (CorsConfigurationSource) source;
    }

}
